﻿using System;
using UnityEngine;

namespace RootMotion.FinalIK
{
	// Token: 0x02000049 RID: 73
	[Serializable]
	public class IKSolverHeuristic : IKSolver
	{
		// Token: 0x06000354 RID: 852 RVA: 0x0002A340 File Offset: 0x00028540
		public bool SetChain(Transform[] hierarchy, Transform root)
		{
			if (this.bones == null || this.bones.Length != hierarchy.Length)
			{
				this.bones = new IKSolver.Bone[hierarchy.Length];
			}
			for (int i = 0; i < hierarchy.Length; i++)
			{
				if (this.bones[i] == null)
				{
					this.bones[i] = new IKSolver.Bone();
				}
				this.bones[i].transform = hierarchy[i];
			}
			base.Initiate(root);
			return base.initiated;
		}

		// Token: 0x06000355 RID: 853 RVA: 0x0002A3C4 File Offset: 0x000285C4
		public void AddBone(Transform bone)
		{
			Transform[] array = new Transform[this.bones.Length + 1];
			for (int i = 0; i < this.bones.Length; i++)
			{
				array[i] = this.bones[i].transform;
			}
			array[array.Length - 1] = bone;
			this.SetChain(array, this.root);
		}

		// Token: 0x06000356 RID: 854 RVA: 0x0002A420 File Offset: 0x00028620
		public override void StoreDefaultLocalState()
		{
			for (int i = 0; i < this.bones.Length; i++)
			{
				this.bones[i].StoreDefaultLocalState();
			}
		}

		// Token: 0x06000357 RID: 855 RVA: 0x0002A454 File Offset: 0x00028654
		public override void FixTransforms()
		{
			for (int i = 0; i < this.bones.Length; i++)
			{
				this.bones[i].FixTransform();
			}
		}

		// Token: 0x06000358 RID: 856 RVA: 0x0002A488 File Offset: 0x00028688
		public override bool IsValid(ref string message)
		{
			if (this.bones.Length == 0)
			{
				message = "IK chain has no Bones.";
				return false;
			}
			if (this.bones.Length < this.minBones)
			{
				message = "IK chain has less than " + this.minBones + " Bones.";
				return false;
			}
			foreach (IKSolver.Bone bone in this.bones)
			{
				if (bone.transform == null)
				{
					message = "One of the Bones is null.";
					return false;
				}
			}
			Transform transform = IKSolver.ContainsDuplicateBone(this.bones);
			if (transform != null)
			{
				message = transform.name + " is represented multiple times in the Bones.";
				return false;
			}
			if (!this.allowCommonParent && !IKSolver.HierarchyIsValid(this.bones))
			{
				message = "Invalid bone hierarchy detected. IK requires for it's bones to be parented to each other in descending order.";
				return false;
			}
			if (!this.boneLengthCanBeZero)
			{
				for (int j = 0; j < this.bones.Length - 1; j++)
				{
					float magnitude = (this.bones[j].transform.position - this.bones[j + 1].transform.position).magnitude;
					if (magnitude == 0f)
					{
						message = "Bone " + j + " length is zero.";
						return false;
					}
				}
			}
			return true;
		}

		// Token: 0x06000359 RID: 857 RVA: 0x00004439 File Offset: 0x00002639
		public override IKSolver.Point[] GetPoints()
		{
			return this.bones;
		}

		// Token: 0x0600035A RID: 858 RVA: 0x0002A5F0 File Offset: 0x000287F0
		public override IKSolver.Point GetPoint(Transform transform)
		{
			for (int i = 0; i < this.bones.Length; i++)
			{
				if (this.bones[i].transform == transform)
				{
					return this.bones[i];
				}
			}
			return null;
		}

		// Token: 0x17000044 RID: 68
		// (get) Token: 0x0600035B RID: 859 RVA: 0x00004441 File Offset: 0x00002641
		public virtual int minBones
		{
			get
			{
				return 2;
			}
		}

		// Token: 0x17000045 RID: 69
		// (get) Token: 0x0600035C RID: 860 RVA: 0x00003A3D File Offset: 0x00001C3D
		public virtual bool boneLengthCanBeZero
		{
			get
			{
				return true;
			}
		}

		// Token: 0x17000046 RID: 70
		// (get) Token: 0x0600035D RID: 861 RVA: 0x00004133 File Offset: 0x00002333
		public virtual bool allowCommonParent
		{
			get
			{
				return false;
			}
		}

		// Token: 0x0600035E RID: 862 RVA: 0x000028E7 File Offset: 0x00000AE7
		public override void OnInitiate()
		{
		}

		// Token: 0x0600035F RID: 863 RVA: 0x000028E7 File Offset: 0x00000AE7
		public override void OnUpdate()
		{
		}

		// Token: 0x06000360 RID: 864 RVA: 0x0002A638 File Offset: 0x00028838
		public void InitiateBones()
		{
			this.chainLength = 0f;
			for (int i = 0; i < this.bones.Length; i++)
			{
				if (i < this.bones.Length - 1)
				{
					this.bones[i].length = (this.bones[i].transform.position - this.bones[i + 1].transform.position).magnitude;
					this.chainLength += this.bones[i].length;
					Vector3 position = this.bones[i + 1].transform.position;
					this.bones[i].axis = Quaternion.Inverse(this.bones[i].transform.rotation) * (position - this.bones[i].transform.position);
					if (this.bones[i].rotationLimit != null)
					{
						if (this.XY)
						{
							if (!(this.bones[i].rotationLimit is RotationLimitHinge))
							{
								Warning.Log("Only Hinge Rotation Limits should be used on 2D IK solvers.", this.bones[i].transform, false);
							}
						}
						this.bones[i].rotationLimit.Disable();
					}
				}
				else
				{
					this.bones[i].axis = Quaternion.Inverse(this.bones[i].transform.rotation) * (this.bones[this.bones.Length - 1].transform.position - this.bones[0].transform.position);
				}
			}
		}

		// Token: 0x17000047 RID: 71
		// (get) Token: 0x06000361 RID: 865 RVA: 0x0002A7F4 File Offset: 0x000289F4
		public virtual Vector3 localDirection
		{
			get
			{
				return this.bones[0].transform.InverseTransformDirection(this.bones[this.bones.Length - 1].transform.position - this.bones[0].transform.position);
			}
		}

		// Token: 0x17000048 RID: 72
		// (get) Token: 0x06000362 RID: 866 RVA: 0x00004444 File Offset: 0x00002644
		public float positionOffset
		{
			get
			{
				return Vector3.SqrMagnitude(this.localDirection - this.lastLocalDirection);
			}
		}

		// Token: 0x06000363 RID: 867 RVA: 0x0002A848 File Offset: 0x00028A48
		public Vector3 GetSingularityOffset()
		{
			if (!this.SingularityDetected())
			{
				return Vector3.zero;
			}
			Vector3 normalized = (this.IKPosition - this.bones[0].transform.position).normalized;
			Vector3 rhs = new Vector3(normalized.y, normalized.z, normalized.x);
			if (this.useRotationLimits && this.bones[this.bones.Length - 2].rotationLimit != null && this.bones[this.bones.Length - 2].rotationLimit is RotationLimitHinge)
			{
				rhs = this.bones[this.bones.Length - 2].transform.rotation * this.bones[this.bones.Length - 2].rotationLimit.axis;
			}
			return Vector3.Cross(normalized, rhs) * this.bones[this.bones.Length - 2].length * 0.5f;
		}

		// Token: 0x06000364 RID: 868 RVA: 0x0002A95C File Offset: 0x00028B5C
		public bool SingularityDetected()
		{
			if (!base.initiated)
			{
				return false;
			}
			Vector3 a = this.bones[this.bones.Length - 1].transform.position - this.bones[0].transform.position;
			Vector3 a2 = this.IKPosition - this.bones[0].transform.position;
			float magnitude = a.magnitude;
			float magnitude2 = a2.magnitude;
			if (magnitude < magnitude2)
			{
				return false;
			}
			if (magnitude < this.chainLength - this.bones[this.bones.Length - 2].length * 0.1f)
			{
				return false;
			}
			if (magnitude == 0f)
			{
				return false;
			}
			if (magnitude2 == 0f)
			{
				return false;
			}
			if (magnitude2 > magnitude)
			{
				return false;
			}
			float num = Vector3.Dot(a / magnitude, a2 / magnitude2);
			return num >= 0.999f;
		}

		// Token: 0x04000223 RID: 547
		public Transform target;

		// Token: 0x04000224 RID: 548
		public float tolerance;

		// Token: 0x04000225 RID: 549
		public int maxIterations = 4;

		// Token: 0x04000226 RID: 550
		public bool useRotationLimits = true;

		// Token: 0x04000227 RID: 551
		public bool XY;

		// Token: 0x04000228 RID: 552
		public IKSolver.Bone[] bones = new IKSolver.Bone[0];

		// Token: 0x04000229 RID: 553
		public Vector3 lastLocalDirection;

		// Token: 0x0400022A RID: 554
		public float chainLength;
	}
}
